﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Package;
using Babel.Parser;
using Babel.Lexer;
using System.ComponentModel;
using System.Reflection;
using Wicresoft.Shell.Core;

namespace Babel
{
    public partial class Resolver : IASTResolver
    {
        public IList<Type> ObjectList = new List<Type>();
        public IList<ElementInfo> Elements;
        //public IList<string> Members;

        public Resolver()
        {
            //Members = new List<string>();
            Elements = new List<ElementInfo>();
        }

        public void AddType(object obj)
        {
            Type type;
            type = obj.GetType();
            if (!ObjectList.Contains(type))
                ObjectList.Add(type);
        }

        public void AddType(Type type)
        {
            if (!ObjectList.Contains(type))
                ObjectList.Add(type);
        }


        #region IASTResolver Members

        public IList<Babel.Declaration> FindCompletions(object result, int line, int col)
        {
            List<Babel.Declaration> declaration = new List<Declaration>();

            string currentText = result.ToString();
            foreach (string command in Babel.Lexer.Scanner.KeyWords)
            {
                if (currentText == string.Empty || command.StartsWith(currentText))
                {
                    declaration.Add(new Declaration(command, command, 0, command));
                }
            }

            return declaration;
        }

        public IList<Babel.Declaration> FindMembers(object result, int line, int col)
        {
            // ManagedMyC.Parser.AAST aast = result as ManagedMyC.Parser.AAST;
            //List<Babel.Declaration> members = new List<Babel.Declaration>();
            //return new List<Babel.Declaration>();
            //foreach (string state in aast.startStates.Keys)
            //    members.Add(new Declaration(state, state, 0, state));
            List<Babel.Declaration> members = new List<Declaration>();
            TokenInfo ti = result as TokenInfo;
            if (ti != null)
            {
                switch (ti.Token)
                {
                    case (int)Babel.Parser.Tokens.KWSHARP:
                        {
                            foreach (string m in Scanner.KeyWords)
                            {
                                members.Add(new Declaration("#" + m, "#" + m, (int)IconImageIndex.Keyword , "#" + m));
                            }
                        }
                        break;
                    case (int)Babel.Parser.Tokens.UMCElement:
                        {
                            foreach (Type t in ObjectList)
                            {
                                members.Add(new Declaration(t.Name, t.Name, (int)IconImageIndex.Class + (int)IconImageIndex.AccessPublic, t.Name));
                            }
                        }
                        break;
                    case (int)Babel.Parser.Tokens.UMCAttribute:
                        {
                            string temp = GetNearest(line + 1);
                            foreach (Type t in ObjectList)
                            {
                                if (t.Name == temp)
                                {                                
                                    //if the type define DesignerAttribute , we need to filter the properties
                                    AttributeCollection attrs = TypeDescriptor.GetAttributes(t);
                                    DesignerAttribute desinger = attrs[typeof(DesignerAttribute)] as DesignerAttribute;
                                    if (desinger != null && !desinger.IsDefaultAttribute())
                                    {
                                        Assembly a = Assembly.GetAssembly(t);
                                        Type inface = a.GetType(t.Namespace + ".I" + t.Name);
                                        if (inface != null)
                                        {
                                            foreach (PropertyInfo p in inface.GetProperties())
                                            {
                                                members.Add(new Declaration(p.Name, p.Name, (int)IconImageIndex.Property + (int)IconImageIndex.AccessPublic, p.Name));
                                            }
                                        }
                                        break;
                                    }
                                    else
                                    {                                    
                                        foreach (PropertyInfo p in t.GetProperties())
                                        {
                                            members.Add(new Declaration(p.Name, p.Name, (int)IconImageIndex.Property + (int)IconImageIndex.AccessPublic, p.Name));
                                        }
                                        break;
                                    }

                                }
                            }
                        }
                        break;
                    //case (int)Babel.Parser.Tokens.UMCDOLLAR:
                    //    {
                    //        foreach (string m in Members)
                    //        {
                    //            members.Add(new Declaration("$" + m, "$" + m, (int)IconImageIndex.Field + (int)IconImageIndex.AccessPublic, "$" + m));
                    //        }
                    //    }
                    //    break;
                    default:
                        break;
                }
            }
            return members;
        }

        public string FindQuickInfo(object result, int line, int col)
        {
            return "unknown";
        }

        public IList<Method> FindMethods(object result, int line, int col, string name)
        {
            return new List<Method>();
        }

        #endregion

        private string GetNearest(int line)
        {
            int k;
            for (k = Elements.Count - 1; k > -1; k--)
            {
                if (Elements[k].line <= line)
                    return Elements[k].ElementName;
            }
            return string.Empty;
        }
    }


    internal enum IconImageIndex
    {
        // access types
        AccessPublic = 0,
        AccessInternal = 1,
        AccessFriend = 2,
        AccessProtected = 3,
        AccessPrivate = 4,
        AccessShortcut = 5,

        Base = 6,
        // Each of the following icon type has 6 versions,
        //corresponding to the access types
        Class = Base * 0,
        Constant = Base * 1,
        Delegate = Base * 2,
        Enumeration = Base * 3,
        EnumMember = Base * 4,
        Event = Base * 5,
        Exception = Base * 6,
        Field = Base * 7,
        Interface = Base * 8,
        Macro = Base * 9,
        Map = Base * 10,
        MapItem = Base * 11,
        Method = Base * 12,
        OverloadedMethod = Base * 13,
        Module = Base * 14,
        Namespace = Base * 15,
        Operator = Base * 16,
        Property = Base * 17,
        Struct = Base * 18,
        Template = Base * 19,
        Typedef = Base * 20,
        Type = Base * 21,
        Union = Base * 22,
        Variable = Base * 23,
        ValueType = Base * 24,
        Intrinsic = Base * 25,
        JavaMethod = Base * 26,
        JavaField = Base * 27,
        JavaClass = Base * 28,
        JavaNamespace = Base * 29,
        JavaInterface = Base * 30,
        // Miscellaneous icons with one icon for each type.
        Error = 187,
        GreyedClass = 188,
        GreyedPrivateMethod = 189,
        GreyedProtectedMethod = 190,
        GreyedPublicMethod = 191,
        BrowseResourceFile = 192,
        Reference = 193,
        Library = 194,
        VBProject = 195,
        VBWebProject = 196,
        CSProject = 197,
        CSWebProject = 198,
        VB6Project = 199,
        CPlusProject = 200,
        Form = 201,
        OpenFolder = 202,
        ClosedFolder = 203,
        Arrow = 204,
        CSClass = 205,
        Snippet = 206,
        Keyword = 207,
        Info = 208,
        CallBrowserCall = 209,
        CallBrowserCallRecursive = 210,
        XMLEditor = 211,
        VJProject = 212,
        VJClass = 213,
        ForwardedType = 214,
        CallsTo = 215,
        CallsFrom = 216,
        Warning = 217,
    }
}
